--*****************************************************************************
--*                                                                           *
--*                         Квадратурный коррелятор                           *
--*                                                                           *
--*****************************************************************************
-- DESIGN  : VHDL Discription of the FPGA XDSP680cp 
-- FILE    : correlator.vhd
-- DATE    : 28.11.2007
-- REVISION: 1.0
-- DESIGNER: Егоров Е.Ю., Панюков А.Г.
-- Descr   : Квадратурный коррелятор 
-- Entities: CORRELATOR
-- Changes :                                                    
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all; 

entity CORRELATOR is port(
	RESET    : in  std_logic;                     -- Сигнал сброса
	
	INDATA   : in  std_logic_vector(7 downto 0);  -- Входные данные
	INREF1   : in  std_logic_vector(7 downto 0);  -- Эталонный сигнал основного канала 
	INREF2   : in  std_logic_vector(7 downto 0);  -- Эталонный сигнал квадатурного канала
	
	EXT_CLK  : in  std_logic;                     -- Тактовый сигнал для перемножителя
	CLK      : in  std_logic;                     -- Тактовый сигнал
	UNLD_EDG : in  std_logic;                     -- Фронт выгрузки данных
	
	OUTENVLP : out std_logic_vector(15 downto 0); -- Выход огибающей в формате 1_8_7
	OUTTST1  : out std_logic_vector(15 downto 0); -- Тестоый выход основного канала
	OUTTST2  : out std_logic_vector(15 downto 0)  -- Тестоый выход квадратурного канала
	);
end CORRELATOR;

architecture RTL of CORRELATOR is

component MULTIPLY_1_8_7_x5 is port(
	RESET : in  std_logic;							-- Сигнал сброса
	CLK   : in  std_logic;							-- Сигнал тактирования
	CLR   : in  std_logic;							-- Фронт начала перемножения
	
	DINA0 : in  std_logic_vector(15 downto 0);		-- 
	DINA1 : in  std_logic_vector(15 downto 0);		--
	DINA2 : in  std_logic_vector(15 downto 0);		-- Входы A
	DINA3 : in  std_logic_vector(15 downto 0);		--
	DINA4 : in  std_logic_vector(15 downto 0);		--
	
	DINB0 : in  std_logic_vector(15 downto 0);		--
	DINB1 : in  std_logic_vector(15 downto 0);		--
	DINB2 : in  std_logic_vector(15 downto 0);		-- Входы B
	DINB3 : in  std_logic_vector(15 downto 0);		--
	DINB4 : in  std_logic_vector(15 downto 0);		--
	
	DOUT0 : out std_logic_vector(15 downto 0);		--
	DOUT1 : out std_logic_vector(15 downto 0);		--
	DOUT2 : out std_logic_vector(15 downto 0);		-- Выходы
	DOUT3 : out std_logic_vector(15 downto 0);		--
	DOUT4 : out std_logic_vector(15 downto 0));
end component;

component SUM_1_8_7 is port(
	RST  : in  std_logic;
	CLK  : in  std_logic;
	CLR  : in  std_logic;
	DINA : in  std_logic_vector(15 downto 0);
	DINB : in  std_logic_vector(15 downto 0);
	DOUT : out std_logic_vector(15 downto 0));
end component;

    signal INSIGNAL   : std_logic_vector(15 downto 0);
	signal REF1SIG    : std_logic_vector(15 downto 0);
	signal REF2SIG    : std_logic_vector(15 downto 0);
    signal MUL2SUM1   : std_logic_vector(15 downto 0);
	signal MUL2SUM2   : std_logic_vector(15 downto 0);
	signal SUM2SQR1   : std_logic_vector(15 downto 0);
	signal SUM2SQR2   : std_logic_vector(15 downto 0);
	signal OUT1       : std_logic_vector(15 downto 0);
	signal OUT2       : std_logic_vector(15 downto 0);
	signal OUT_FINAL  : std_logic_vector(15 downto 0);
	signal NEW_CYCLE  : std_logic;
	signal ZEROS      : std_logic_vector(15 downto 0);
	
begin

INSIGNAL(15) <= INDATA(7);
INSIGNAL(14 downto 7) <= INDATA when INDATA(7) = '0' else not(INDATA) + '1';
INSIGNAL(6 downto 0) <= "0000000";

REF1SIG(15) <= INREF1(7);
REF1SIG(14 downto 7) <= INREF1 when INREF1(7) = '0' else not(INREF1) + '1';
REF1SIG(6 downto 0) <= "0000000";

REF2SIG(15) <= INREF2(7);
REF2SIG(14 downto 7) <= INREF2 when INREF2(7) = '0' else not(INREF2) + '1';
REF2SIG(6 downto 0) <= "0000000";

ZEROS <= x"0000";

MUL_inst: MULTIPLY_1_8_7_x5 port map(
	RESET => RESET,
	CLK   => EXT_CLK,
	CLR   => CLK,
	
	DINA0 => INSIGNAL,  	 
	DINB0 => REF1SIG,	
	DOUT0 => MUL2SUM1,	

	DINA1 => INSIGNAL, 	
	DINB1 => REF2SIG,	
	DOUT1 => MUL2SUM2,	

	DINA2 => SUM2SQR1,	 
	DINB2 => SUM2SQR1,	 
	DOUT2 => OUT1,    	 
         
	DINA3 => SUM2SQR2,	
	DINB3 => SUM2SQR2,    	
	DOUT3 => OUT2,	
         
	DINA4 => ZEROS,	
	DINB4 => ZEROS,	
	DOUT4 => open
	);

 SUM1_inst: SUM_1_8_7 port map(
	RST  => RESET,
	CLK  => CLK,
	CLR  => NEW_CYCLE,
	DINA => MUL2SUM1, 
	DINB => SUM2SQR1, 
	DOUT => SUM2SQR1);

SUM2_inst: SUM_1_8_7 port map(
	RST  => RESET,
	CLK  => CLK,
	CLR  => NEW_CYCLE,
	DINA => MUL2SUM2, 
	DINB => SUM2SQR2, 
	DOUT => SUM2SQR2);

	
SUM_FINAL_inst: SUM_1_8_7 port map(
	RST  => RESET,
	CLK  => CLK,
	CLR  => NEW_CYCLE,
	DINA => OUT1, 
	DINB => OUT2, 
	DOUT => OUT_FINAL);

process(RESET, UNLD_EDG, CLK)
begin
	if RESET = '1' then
		OUTENVLP  <= X"0000";
		OUTTST1   <= X"0000";
		OUTTST2   <= X"0000";
	elsif Rising_Edge(CLK) then
		if (UNLD_EDG = '1' and NEW_CYCLE = '0') then
			OUTENVLP <= OUT_FINAL;
			OUTTST1 <= SUM2SQR1;
			OUTTST2 <= SUM2SQR2;
		end if;
	end if;
end process;
	
process(RESET, UNLD_EDG, CLK)
begin
	if RESET = '1' then
		NEW_CYCLE <= '0';
	elsif Rising_edge(CLK) then
		if UNLD_EDG = '1' then
			NEW_CYCLE <= '1';
		else 
			NEW_CYCLE <= '0';
		end if;
	end if;
end process;	
	
end RTL;
